package cn.zifangsky.controller;

import cn.zifangsky.common.Constants;
import cn.zifangsky.common.ReturnModel;
import cn.zifangsky.common.SpringContextUtils;
import cn.zifangsky.model.AuthorizationResponse;
import cn.zifangsky.model.User;
import cn.zifangsky.utils.EncryptUtils;
import cn.zifangsky.utils.HttpUtil;
import cn.zifangsky.utils.JsonUtils;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.net.URI;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录
 * @author zifangsky
 * @date 2018/7/9
 * @since 1.0.0
 */
@Controller
public class LoginController {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${own.oauth2.client-id}")
    private String clientId;

    @Value("${own.oauth2.scope}")
    private String scope;

    @Value("${own.oauth2.client-secret}")
    private String clientSecret;

    @Value("${own.oauth2.user-authorization-uri}")
    private String authorizationUri;

    @Value("${own.oauth2.access-token-uri}")
    private String accessTokenUri;

    @Value("${own.oauth2.oauth2-logout-uri}")
    private String oauth2LogoutUri;

    @Value("${own.oauth2.resource.userInfoUri}")
    private String userInfoUri;

    @Value("${own.oauth2.login.collback.redirectUrl}")
    private String loginRedirectUrl;

    /**
     * 登录验证（实际登录调用认证服务器）
     * @author zifangsky
     * @date 2018/7/25 16:42
     * @since 1.0.0
     * @param request HttpServletRequest
     * @return org.springframework.web.servlet.ModelAndView
     */
    @RequestMapping("/login")
    public ModelAndView login(HttpServletRequest request){
        //当前系统登录成功之后的回调URL
        String redirectUrl = request.getParameter("redirectUrl");

        //当前系统请求认证服务器成功之后返回的Authorization Code
        String code = request.getParameter("code");

        //最后重定向的URL
        String resultUrl = "redirect:";
        HttpSession session = request.getSession();
        //当前请求路径
        String currentUrl = loginRedirectUrl!=null?loginRedirectUrl:request.getRequestURL().toString();
        Map<String, String[]> parameterMap = request.getParameterMap();
        String parameterJson = JsonUtils.toJson(parameterMap);
        System.out.println(parameterJson);
        //code为空，则说明当前请求不是认证服务器的回调请求，则重定向URL到认证服务器登录
        if(StringUtils.isBlank(code)){
            //如果存在回调URL，则将这个URL添加到session
            if(StringUtils.isNoneBlank(redirectUrl)){
                session.setAttribute(Constants.SESSION_LOGIN_REDIRECT_URL,redirectUrl);
            }

            //生成随机的状态码，用于防止CSRF攻击
            String state = EncryptUtils.getRandomStr1(12);
            session.setAttribute(Constants.SESSION_AUTH_CODE_STATUS, state);
            //拼装请求Authorization Code的地址
            resultUrl += MessageFormat.format(authorizationUri,clientId,state,currentUrl);
        }else{
            //2. 通过Authorization Code获取Access Token
            Map<String,Object> param = new HashMap();
            param.put("client_id",clientId);
            param.put("client_secret",clientSecret);
            param.put("code",code);
            param.put("redirect_uri",currentUrl);
            param.put("grant_type","authorization_code");
            //URI uri = restTemplate.postForLocation(accessTokenUri, param);
            String responseStr = HttpUtil.httpRequest(accessTokenUri,param,"POST");
            AuthorizationResponse response = JsonUtils.fromJson(responseStr, AuthorizationResponse.class);
            String access_token = response.getAccess_token();
            //如果正常返回
            if(StringUtils.isNoneBlank(access_token)){
                System.out.println(response);
                String id_token = response.getId_token();
                //2.1 将Access Token存到session
                session.setAttribute(Constants.SESSION_ACCESS_TOKEN,access_token);
                session.setAttribute("id_token",id_token);

                //2.2 再次查询用户基础信息，并将用户ID存到session
                HashMap headParam = new HashMap();
                headParam.put("Authorization","Bearer "+access_token);
                HashMap userInfoMap = null;
                try {
                    String userInfoStr = HttpUtil.get("https://ztt-sso.asuncloud.net/userinfo", headParam);
                    userInfoMap = JsonUtils.fromJson(userInfoStr,HashMap.class);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                if(userInfoMap==null) {
                    //如果存在回调URL，则将这个URL添加到session
                    if(StringUtils.isNoneBlank(redirectUrl)){
                        session.setAttribute(Constants.SESSION_LOGIN_REDIRECT_URL,redirectUrl);
                    }

                    //生成随机的状态码，用于防止CSRF攻击
                    String status = EncryptUtils.getRandomStr1(6);
                    session.setAttribute(Constants.SESSION_AUTH_CODE_STATUS, status);
                    //拼装请求Authorization Code的地址
                    resultUrl += MessageFormat.format(authorizationUri,clientId,status,currentUrl);
                    return new ModelAndView(resultUrl);
                }
                userInfoMap.put("id_token",id_token);
                if(StringUtils.isNoneBlank(userInfoMap.get("employee_id")==null?"":userInfoMap.get("employee_id").toString())||StringUtils.isNoneBlank(userInfoMap.get("username").toString())){
                    session.setAttribute(Constants.SESSION_USER,userInfoMap);
                }
            }

            //3. 从session中获取回调URL，并返回
            redirectUrl = (String) session.getAttribute(Constants.SESSION_LOGIN_REDIRECT_URL);
            session.removeAttribute("redirectUrl");
            if(StringUtils.isNoneBlank(redirectUrl)){
                resultUrl += redirectUrl;
            }else{

                String host = request.getHeader("host");
                String httpsHost = "https://"+host;
                resultUrl += httpsHost+"/user/userIndex";
            }
        }

        return new ModelAndView(resultUrl);
    }

    @GetMapping("/logout")
    public ModelAndView logout(HttpServletRequest request) {
        String url = request.getRequestURL().toString();
        HttpSession session = request.getSession();
        String accessToken = (String) session.getAttribute(Constants.SESSION_ACCESS_TOKEN);
        String id_token = (String) session.getAttribute("id_token");
        //在认证服务器发送退出登录请求
        String returnModel = restTemplate.getForObject(oauth2LogoutUri, String.class
                ,id_token);
        System.out.println("退出登录请求返回结果:"+JsonUtils.toJson(returnModel));
        session.removeAttribute(Constants.SESSION_USER);
        session.removeAttribute(Constants.SESSION_ACCESS_TOKEN);
        session.removeAttribute("id_token");
        session.removeAttribute(Constants.SESSION_LOGIN_REDIRECT_URL);
        HashMap headParam = new HashMap();
        headParam.put("Authorization","Bearer "+accessToken);
        HashMap userInfoMap = null;
        try {
            //测试调用中天OAuth2.0认证平台退出登录后是否还可以通过accessToken获取用户信息
            String userInfoStr = HttpUtil.get("https://ztt-sso.asuncloud.net/userinfo", headParam);
            userInfoMap = JsonUtils.fromJson(userInfoStr,HashMap.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String host = request.getHeader("host");
        String httpsHost = "https://"+host;
        return new ModelAndView("redirect:"+httpsHost+"/loginPage");
    }

}
